#pragma once
#include <windows.h>

#pragma comment(lib, "user32.lib")
#pragma comment(lib, "advapi32.lib")

namespace shutdowntimer {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;
	using namespace System::Threading;

	/// <summary>
	/// Summary for Form1
	/// </summary>
	public ref class Form1 : public System::Windows::Forms::Form
	{
	public:

		delegate void NewTimeCallback(System::Object ^obj, int);
		Thread^ newThread;

		Form1(void)
		{
			InitializeComponent();
			newThread = gcnew Thread(gcnew ParameterizedThreadStart(&SafeThread ));
			//
			//TODO: Add the constructor code here
			//
		}

	protected:
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		~Form1()
		{
			if (components)
			{
				delete components;
			}
			if (newThread->IsAlive) {
				newThread->Abort();
			}
		}
	private: System::Windows::Forms::Label^  shutdownin_label;
	protected: 
	private: System::Windows::Forms::NumericUpDown^  h_updown;
	private: System::Windows::Forms::Label^  h_label;
	private: System::Windows::Forms::Label^  min_label;
	private: System::Windows::Forms::NumericUpDown^  min_updown;
	private: System::Windows::Forms::Label^  sec_label;
	private: System::Windows::Forms::NumericUpDown^  sec_updown;
	private: System::Windows::Forms::Button^  stop_button;
	private: System::Windows::Forms::Button^  start_button;

	private:
		/// <summary>
		/// Required designer variable.
		/// </summary>
		System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		void InitializeComponent(void)
		{
			this->shutdownin_label = (gcnew System::Windows::Forms::Label());
			this->h_updown = (gcnew System::Windows::Forms::NumericUpDown());
			this->h_label = (gcnew System::Windows::Forms::Label());
			this->min_label = (gcnew System::Windows::Forms::Label());
			this->min_updown = (gcnew System::Windows::Forms::NumericUpDown());
			this->sec_label = (gcnew System::Windows::Forms::Label());
			this->sec_updown = (gcnew System::Windows::Forms::NumericUpDown());
			this->stop_button = (gcnew System::Windows::Forms::Button());
			this->start_button = (gcnew System::Windows::Forms::Button());
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->h_updown))->BeginInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->min_updown))->BeginInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->sec_updown))->BeginInit();
			this->SuspendLayout();
			// 
			// shutdownin_label
			// 
			this->shutdownin_label->AutoSize = true;
			this->shutdownin_label->Location = System::Drawing::Point(13, 13);
			this->shutdownin_label->Name = L"shutdownin_label";
			this->shutdownin_label->Size = System::Drawing::Size(183, 13);
			this->shutdownin_label->TabIndex = 0;
			this->shutdownin_label->Text = L"Das System wird heruntergefahren in:";
			// 
			// h_updown
			// 
			this->h_updown->Location = System::Drawing::Point(202, 11);
			this->h_updown->Maximum = System::Decimal(gcnew cli::array< System::Int32 >(4) {24, 0, 0, 0});
			this->h_updown->Name = L"h_updown";
			this->h_updown->Size = System::Drawing::Size(39, 20);
			this->h_updown->TabIndex = 1;
			// 
			// h_label
			// 
			this->h_label->AutoSize = true;
			this->h_label->Location = System::Drawing::Point(248, 13);
			this->h_label->Name = L"h_label";
			this->h_label->Size = System::Drawing::Size(13, 13);
			this->h_label->TabIndex = 2;
			this->h_label->Text = L"h";
			// 
			// min_label
			// 
			this->min_label->AutoSize = true;
			this->min_label->Location = System::Drawing::Point(313, 13);
			this->min_label->Name = L"min_label";
			this->min_label->Size = System::Drawing::Size(23, 13);
			this->min_label->TabIndex = 4;
			this->min_label->Text = L"min";
			// 
			// min_updown
			// 
			this->min_updown->Location = System::Drawing::Point(267, 11);
			this->min_updown->Maximum = System::Decimal(gcnew cli::array< System::Int32 >(4) {59, 0, 0, 0});
			this->min_updown->Name = L"min_updown";
			this->min_updown->Size = System::Drawing::Size(39, 20);
			this->min_updown->TabIndex = 3;
			// 
			// sec_label
			// 
			this->sec_label->AutoSize = true;
			this->sec_label->Location = System::Drawing::Point(388, 13);
			this->sec_label->Name = L"sec_label";
			this->sec_label->Size = System::Drawing::Size(12, 13);
			this->sec_label->TabIndex = 6;
			this->sec_label->Text = L"s";
			// 
			// sec_updown
			// 
			this->sec_updown->Location = System::Drawing::Point(342, 11);
			this->sec_updown->Maximum = System::Decimal(gcnew cli::array< System::Int32 >(4) {59, 0, 0, 0});
			this->sec_updown->Name = L"sec_updown";
			this->sec_updown->Size = System::Drawing::Size(39, 20);
			this->sec_updown->TabIndex = 5;
			this->sec_updown->Value = System::Decimal(gcnew cli::array< System::Int32 >(4) {1, 0, 0, 0});
			// 
			// stop_button
			// 
			this->stop_button->Enabled = false;
			this->stop_button->Location = System::Drawing::Point(334, 37);
			this->stop_button->Name = L"stop_button";
			this->stop_button->Size = System::Drawing::Size(75, 23);
			this->stop_button->TabIndex = 7;
			this->stop_button->Text = L"Stop";
			this->stop_button->UseVisualStyleBackColor = true;
			this->stop_button->Click += gcnew System::EventHandler(this, &Form1::stop_button_Click);
			// 
			// start_button
			// 
			this->start_button->Location = System::Drawing::Point(251, 37);
			this->start_button->Name = L"start_button";
			this->start_button->Size = System::Drawing::Size(75, 23);
			this->start_button->TabIndex = 8;
			this->start_button->Text = L"Start";
			this->start_button->UseVisualStyleBackColor = true;
			this->start_button->Click += gcnew System::EventHandler(this, &Form1::start_button_Click);
			// 
			// Form1
			// 
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(421, 74);
			this->Controls->Add(this->start_button);
			this->Controls->Add(this->stop_button);
			this->Controls->Add(this->sec_label);
			this->Controls->Add(this->sec_updown);
			this->Controls->Add(this->min_label);
			this->Controls->Add(this->min_updown);
			this->Controls->Add(this->h_label);
			this->Controls->Add(this->h_updown);
			this->Controls->Add(this->shutdownin_label);
			this->Name = L"Form1";
			this->Text = L"Shutdowntimer";
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->h_updown))->EndInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->min_updown))->EndInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->sec_updown))->EndInit();
			this->ResumeLayout(false);
			this->PerformLayout();

		}
#pragma endregion


		static void setValues(System::Object ^obj, int sec_remaining) {
			 Form1 ^ob = (Form1^) obj;
			if(ob->sec_updown->InvokeRequired || ob->min_updown->InvokeRequired || ob->h_updown->InvokeRequired)
			{
				NewTimeCallback ^d = gcnew NewTimeCallback(setValues);
				ob->Invoke(d,gcnew array<System::Object^>{ob, sec_remaining});				
			} else {
				ob->sec_updown->Value = sec_remaining % 60;
				ob->min_updown->Value = (sec_remaining / 60) % 60;
				ob->h_updown->Value = sec_remaining / (60*60);
			}
		}

		static void SafeThread(System::Object ^obj)
		{

			 Form1 ^ob = (Form1^) obj;
			
				int sec_remaining = (int)ob->h_updown->Value * 60 * 60 + (int)ob->min_updown->Value * 60 + (int)ob->sec_updown->Value;
				while (sec_remaining > 0) {
					Thread::CurrentThread->Sleep(1000);
					sec_remaining = (int)ob->h_updown->Value * 60 * 60 + (int)ob->min_updown->Value * 60 + (int)ob->sec_updown->Value;
					if (! ob->start_button->Enabled) {
						sec_remaining -= 1;
					}
					setValues(obj, sec_remaining);
				}
				// Times up
				HANDLE hToken; 
			    TOKEN_PRIVILEGES tkp; 
 
			    // Get a token for this process. 
 
			   if (!OpenProcessToken(GetCurrentProcess(), 
					TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 
				  return; 
 
			   // Get the LUID for the shutdown privilege. 
 
			   LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, 
					&tkp.Privileges[0].Luid); 
 
			   tkp.PrivilegeCount = 1;  // one privilege to set    
			   tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
 
			   // Get the shutdown privilege for this process. 
 
			   AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, 
					(PTOKEN_PRIVILEGES)NULL, 0); 
 
			   if (GetLastError() != ERROR_SUCCESS) 
				  return; 
 
			   // Shut down the system and force all applications to close. 
 
			   if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 
						   SHTDN_REASON_MAJOR_OPERATINGSYSTEM |
						   SHTDN_REASON_MINOR_UPGRADE |
						   SHTDN_REASON_FLAG_PLANNED)) 
				  return; 

			   //shutdown was successful
			   return;
		}




	private: System::Void start_button_Click(System::Object^  sender, System::EventArgs^  e) {
				 if (! newThread->IsAlive) {
					newThread->Start(this);
				 }
				 start_button->Enabled = false;
				 stop_button->Enabled = true;
			 }
private: System::Void stop_button_Click(System::Object^  sender, System::EventArgs^  e) {
			 start_button->Enabled = true;
			 stop_button->Enabled = false;
		 }
};
}

